package Computer;

import java.util.ArrayDeque;
import java.util.Queue;

/**
 * Device class.
 * 
 * @author Stephen Amos, Zach Turk, Dickson Kwong
 *
 */

public class Device {

	//The maximum number of steps before this device will be ready to handle an interrupt/trap
	protected final static int MAXINTERVAL = 10;
	
	protected int steps_until_interrupt;
	protected Computer.Handler device_handler;
	protected Queue<PCB> blocked;
	protected String name;
	
	// boolean flag denotes whether there is a ready process to retrieve
	protected boolean ready;
	
	/**
	 * Create a new device with given interval that interrupts with given handler
	 * @param starting_interval
	 * @param handler
	 */
	protected Device(int starting_interval, Computer.Handler handler) {
		steps_until_interrupt = starting_interval;
		device_handler = handler;
		blocked = new ArrayDeque<PCB>();
		ready = false;
		name = "Device";
	}
	
	
	/**
	 * Creates a new device with given hander that interrupts at random intervals
	 * @param handler
	 */
	protected Device(Computer.Handler handler) {
		this((int) (Math.random() * MAXINTERVAL), handler);
	}
	
	/**
	 * @return The interrupt being sent to the computer on this step
	 */
	public Computer.Handler poll(){
		if (steps_until_interrupt > 0) {
			steps_until_interrupt--;
			return null;
		}
		
		int new_interval = (int) (Math.random() * MAXINTERVAL);
		steps_until_interrupt = new_interval;
		ready = true;
		return device_handler;
	}
	
	/**
	 * @param pcb A PCB that is waiting on this device
	 */
	public void addProcess(PCB pcb) {
		blocked.add(pcb);
	}
	
	public PCB getProcess() {
		if (ready) {
			ready = false;
			return blocked.poll();
		}
		return null;
	}
	
	public String toString() {
		return name;
	}
}
